package com.bocloud.cmp.service.app.monitor;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Repository;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.entity.app.resource.OpenshiftMonitor;
import com.bocloud.common.model.BaseResult;
import com.bocloud.common.utils.ListTool;
/**
 * @author Zaney
 * @data:2017年4月20日
 * @describe:第一次线程池client
 */
@Repository("appFirstClient")
public class AppFirstClient {
	private static Logger logger = LoggerFactory.getLogger(AppFirstClient.class);
	private AppSecondClient appSecondClient;
	
	public void setAppSecondClient(AppSecondClient appSecondClient) {
		this.appSecondClient = appSecondClient;
	}

	// *==============================累加cpu/memory/network,求平均值================================*//
	@SuppressWarnings("unchecked")
	public JSONObject cpu(OpenshiftMonitor monitor, JSONArray labels) {
		List<OpenshiftMonitor> monitors = new ArrayList<OpenshiftMonitor>();
		List<Double> sumList = new ArrayList<Double>();
		JSONArray avgArray = new JSONArray();
		JSONObject cpuObject = new JSONObject();
		// 给sumList初始化数据
		for (int i = 0; i < 15; i++) {
			sumList.add(0.00);
		}
		// 累加所有labels的数值
		for (Object object : labels) {
			// 给openshiftMonitor赋值
			Map<String, String> parseObject = JSONObject.parseObject(object.toString(), Map.class);
			OpenshiftMonitor openshiftMonitor = new OpenshiftMonitor();
			BeanUtils.copyProperties(monitor, openshiftMonitor);
			openshiftMonitor.setLabels(parseObject.get("label"));
			openshiftMonitor.setNamespace(parseObject.get("namespace"));
			monitors.add(openshiftMonitor);	
		}
		// 调用获取cpu数据
		List<JSONArray> cpuMonitors = getCpuMonitor(monitors);
		if (!ListTool.isEmpty(cpuMonitors)) {
			for (JSONArray cpuMonitor : cpuMonitors) {
				for (int i = 0; i < cpuMonitor.size(); i++) {
					Double value = sumList.get(i);
					value += Double.valueOf(cpuMonitor.get(i).toString());
					sumList.set(i, value);
				}
			}
			// 取平均值
			for (int i = 0; i < sumList.size(); i++) {
				BigDecimal avg = new BigDecimal(sumList.get(i)).divide(new BigDecimal(labels.size()), 2,
						RoundingMode.HALF_UP);
				avgArray.add(avg);
			}
		}
		cpuObject.put("name", "CPU");
		cpuObject.put("data", avgArray);
		return cpuObject;
	}

	@SuppressWarnings("unchecked")
	public JSONObject memory(OpenshiftMonitor monitor, JSONArray labels) {
		List<OpenshiftMonitor> monitors = new ArrayList<OpenshiftMonitor>();
		List<Double> sumList = new ArrayList<Double>();
		JSONArray avgArray = new JSONArray();
		JSONObject memoryObject = new JSONObject();
		JSONArray dates = new JSONArray();
		// 给sumList初始化数据
		for (int i = 0; i < 15; i++) {
			sumList.add(0.00);
		}
		// 累加所有labels的数值
		for (Object object : labels) {
			// 给openshiftMonitor赋值
			Map<String, String> parseObject = JSONObject.parseObject(object.toString(), Map.class);
			OpenshiftMonitor openshiftMonitor = new OpenshiftMonitor();
			BeanUtils.copyProperties(monitor, openshiftMonitor);
			openshiftMonitor.setLabels(parseObject.get("label"));
			openshiftMonitor.setNamespace(parseObject.get("namespace"));
			monitors.add(openshiftMonitor);
		}
		// 调用获取memory数据
		JSONObject memoryMonitor = getMemoryMonitor(monitors);
		List<JSONArray> memoryArrays = (List<JSONArray>) memoryMonitor.get("memorys");
		//获取时间
		dates = (JSONArray) memoryMonitor.get("dates");
		//获取监控信息
		if (!ListTool.isEmpty(memoryArrays)) {
			for (JSONArray memoryArray : memoryArrays) {
				for (int i = 0; i < memoryArray.size(); i++) {
					Double value = sumList.get(i);
					value += Double.valueOf(memoryArray.get(i).toString());
					sumList.set(i, value);
				}
			}
			// 取平均值
			for (int i = 0; i < sumList.size(); i++) {
				BigDecimal avg = new BigDecimal(sumList.get(i)).divide(new BigDecimal(labels.size()), 2,
						RoundingMode.HALF_UP);
				avgArray.add(avg);
			}
		}
		memoryObject.put("name", "Memory");
		memoryObject.put("data", avgArray);
		memoryObject.put("dates", dates);
		return memoryObject;
	}

	@SuppressWarnings("unchecked")
	public JSONObject networkRx(OpenshiftMonitor monitor, JSONArray labels) {
		List<OpenshiftMonitor> monitors = new ArrayList<OpenshiftMonitor>();
		List<Double> sumList = new ArrayList<Double>();
		JSONArray avgArray = new JSONArray();
		JSONObject networkRx = new JSONObject();
		// 给sumList初始化数据
		for (int i = 0; i < 15; i++) {
			sumList.add(0.00);
		}
		// 累加所有labels的数值
		for (Object object : labels) {
			// 给openshiftMonitor赋值
			Map<String, String> parseObject = JSONObject.parseObject(object.toString(), Map.class);
			OpenshiftMonitor openshiftMonitor = new OpenshiftMonitor();
			BeanUtils.copyProperties(monitor, openshiftMonitor);
			openshiftMonitor.setLabels(parseObject.get("label"));
			openshiftMonitor.setNamespace(parseObject.get("namespace"));
			monitors.add(openshiftMonitor);
		}
		// 调用获取networkRx数据
		List<JSONArray> networkRxMonitors = getNetworkRxMonitor(monitors);
		if (!ListTool.isEmpty(networkRxMonitors)) {
			for (JSONArray networkMonitorRx : networkRxMonitors) {
				for (int i = 0; i < networkMonitorRx.size(); i++) {
					Double value = sumList.get(i);
					value += Double.valueOf(networkMonitorRx.get(i).toString());
					sumList.set(i, value);
				}
			}
			// 取平均值
			for (int i = 0; i < sumList.size(); i++) {
				BigDecimal avg = new BigDecimal(sumList.get(i)).divide(new BigDecimal(labels.size()), 2,
						RoundingMode.HALF_UP);
				avgArray.add(avg);
			}
		}
		networkRx.put("name", "Received");
		networkRx.put("data", avgArray);
		return networkRx;
	}

	@SuppressWarnings("unchecked")
	public JSONObject networkTx(OpenshiftMonitor monitor, JSONArray labels) {
		List<OpenshiftMonitor> monitors = new ArrayList<OpenshiftMonitor>();
		List<Double> sumList = new ArrayList<Double>();
		JSONArray avgArray = new JSONArray();
		JSONObject networkTx = new JSONObject();
		// 给sumList初始化数据
		for (int i = 0; i < 15; i++) {
			sumList.add(0.00);
		}
		// 累加所有labels的数值
		for (Object object : labels) {
			// 给openshiftMonitor赋值
			Map<String, String> parseObject = JSONObject.parseObject(object.toString(), Map.class);
			OpenshiftMonitor openshiftMonitor = new OpenshiftMonitor();
			BeanUtils.copyProperties(monitor, openshiftMonitor);
			openshiftMonitor.setLabels(parseObject.get("label"));
			openshiftMonitor.setNamespace(parseObject.get("namespace"));
			monitors.add(openshiftMonitor);
		}
		// 调用获取networkTx数据
		List<JSONArray> networkTxMonitors = getNetworkTxMonitor(monitors);
		if (!ListTool.isEmpty(networkTxMonitors)) {
			for (JSONArray networkMonitorTx : networkTxMonitors) {
				for (int i = 0; i < networkMonitorTx.size(); i++) {
					Double value = sumList.get(i);
					value += Double.valueOf(networkMonitorTx.get(i).toString());
					sumList.set(i, value);
				}
			}			
			// 取平均值
			for (int i = 0; i < sumList.size(); i++) {
				BigDecimal avg = new BigDecimal(sumList.get(i)).divide(new BigDecimal(labels.size()), 2,
						RoundingMode.HALF_UP);
				avgArray.add(avg);
			}
		}
		networkTx.put("name", "Send");
		networkTx.put("data", avgArray);
		return networkTx;
	}
	
	// *=============================pod的cpu/memory/network监控信息数据处理============================*//
		
	public JSONObject getMemoryMonitor(List<OpenshiftMonitor> memoryMonitors) {
		JSONObject object = new JSONObject();
		List<JSONArray> memorysAll = new ArrayList<JSONArray>();
		JSONArray dates = new JSONArray();
		try {
			List<JSONArray> memoryObjects = appSecondClient.batch(memoryMonitors);
			if (!ListTool.isEmpty(memoryObjects)) {
				// 获取存储信息
				for (JSONArray jsonArray : memoryObjects) {
					JSONArray memorys = new JSONArray();
					for (Object message : jsonArray) {
						JSONObject obj = JSONObject.parseObject(message.toString());
						// 统计时间
						if (obj.containsKey("start")) {
							if (dates.size() <= 14) {
								dates.add(obj.getString("start"));
							}
						}
						// 计算内存信息
						if (obj.containsKey("avg")) {
							BigDecimal avg = new BigDecimal(obj.getString("avg"));
							avg = avg.divide(new BigDecimal(1000).multiply(new BigDecimal(1000)), 2, RoundingMode.HALF_UP);
							memorys.add(avg);
						}
					}
					memorysAll.add(memorys);
				}
			}
			logger.warn("memory信息为null");
			object.put("dates", dates);
			object.put("memorys", memorysAll);
			return object;
		} catch (Exception e) {
			logger.error("获取memory监控信息失败", e);
			return null;
		}
	}

	public List<JSONArray> getCpuMonitor(List<OpenshiftMonitor> cpuMonitors) {
		List<JSONArray> cpuAll = new ArrayList<JSONArray>();
		try {
			List<JSONArray> cpuObjects = appSecondClient.batch(cpuMonitors);
			if (!ListTool.isEmpty(cpuObjects)) {
				for (JSONArray jsonArray : cpuObjects) {
					JSONArray cpus = new JSONArray();
					for (int i = 1; i < jsonArray.size(); i++) {
						JSONObject firstCpu = JSONObject.parseObject(jsonArray.get(i - 1).toString());
						JSONObject secondCpu = JSONObject.parseObject(jsonArray.get(i).toString());
						if (firstCpu.containsKey("avg") && secondCpu.containsKey("avg")) {
							BigDecimal firstAvg = new BigDecimal(firstCpu.getString("avg"));
							BigDecimal secondAvg = new BigDecimal(secondCpu.getString("avg"));
							// monitor.getBucketDuration()时间单位ms
							// ,乘以1000000转换成ns,与avg的单位（ns）符合
							BigDecimal time = new BigDecimal(cpuMonitors.get(0).getBucketDuration()).multiply(new BigDecimal(1000000));
							// 计算cpu监控信息
							BigDecimal cpu = (secondAvg.subtract(firstAvg).multiply(new BigDecimal(1000))).divide(time, 0,
									RoundingMode.HALF_UP);
							cpus.add(cpu.abs());
						}
					}
					cpuAll.add(cpus);
				}
				return cpuAll;
			}
			logger.warn("cpu监控信息为null");
			return cpuAll;
		} catch (Exception e) {
			logger.error("获取cpu监控信息失败", e);
			return null;
		}
	}

	public List<JSONArray> getNetworkTxMonitor(List<OpenshiftMonitor> netTxMonitors) {
		List<JSONArray> networkAll = new ArrayList<JSONArray>();
		try {
			List<JSONArray> netTxObjects = appSecondClient.batch(netTxMonitors);
			// tx
			if (!ListTool.isEmpty(netTxObjects)) {
				for (JSONArray jsonArray : netTxObjects) {
					JSONArray networks = new JSONArray();
					for (int i = 1; i < jsonArray.size(); i++) {
						JSONObject firstObj = JSONObject.parseObject(jsonArray.get(i - 1).toString());
						JSONObject secondObj = JSONObject.parseObject(jsonArray.get(i).toString());
						if (firstObj.containsKey("avg") && secondObj.containsKey("avg")) {
							BigDecimal firstAvg = new BigDecimal(firstObj.getString("avg")).divide(new BigDecimal(1000));
							BigDecimal secondAvg = new BigDecimal(secondObj.getString("avg")).divide(new BigDecimal(1000));
							// 计算网络数据信息
							BigDecimal time = new BigDecimal(netTxMonitors.get(0).getBucketDuration()).divide(new BigDecimal(1000), 2,
									RoundingMode.HALF_UP);
							BigDecimal net = secondAvg.subtract(firstAvg).divide(time, 2, RoundingMode.HALF_UP);
							networks.add(net.abs());
						}
					}
					networkAll.add(networks);
				}
				return networkAll;
			}
			logger.warn("网络监控，连接异常");
			return networkAll;
		} catch (Exception e) {
			logger.error("获取network监控信息失败", e);
			return null;
		}
	}

	public List<JSONArray> getNetworkRxMonitor(List<OpenshiftMonitor> netRxMonitors) {
		List<JSONArray> networkAll = new ArrayList<JSONArray>();
		try {
			List<JSONArray> netRxObject = appSecondClient.batch(netRxMonitors);
			// rx
			if (!ListTool.isEmpty(netRxObject)) {
				for (JSONArray jsonArray : netRxObject) {
					JSONArray networks = new JSONArray();
					for (int i = 1; i < jsonArray.size(); i++) {
						JSONObject firstObj = JSONObject.parseObject(jsonArray.get(i - 1).toString());
						JSONObject secondObj = JSONObject.parseObject(jsonArray.get(i).toString());
						if (firstObj.containsKey("avg") && secondObj.containsKey("avg")) {
							BigDecimal firstAvg = new BigDecimal((firstObj.getString("avg"))).divide(new BigDecimal(1000));
							BigDecimal secondAvg = new BigDecimal((secondObj.getString("avg"))).divide(new BigDecimal(1000));
							// 计算网络数据信息
							BigDecimal time = new BigDecimal(netRxMonitors.get(0).getBucketDuration()).divide(new BigDecimal(1000), 2,
									RoundingMode.HALF_UP);
							BigDecimal net = secondAvg.subtract(firstAvg).divide(time, 2, RoundingMode.HALF_UP);
							networks.add(net.abs());
						}
					}
					networkAll.add(networks);
				}
				return networkAll;
			}	
			logger.warn("网络监控，连接异常");
			return networkAll;
		} catch (Exception e) {
			logger.error("获取network监控信息失败", e);
			return null;
		}
	}
		
		/**
		 * 应用线程池
		 * @param monitors
		 * @return
		 * @throws Exception
		 */
		public List<JSONObject> appBatch(List<OpenshiftMonitor> monitors, JSONArray labels) throws Exception {
			ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() + 1);
			CompletionService<BaseResult<JSONObject>> completionService = new ExecutorCompletionService<>(executor);
			if (ListTool.isEmpty(monitors)) {
				return null;
			}
			for (OpenshiftMonitor monitor : monitors) {
				AppFirstTask task = new AppFirstTask(monitor, labels);
				completionService.submit(task);
			}
			List<JSONObject> objectList = new ArrayList<JSONObject>();
			int completeTask = 0;
			int timeout = 1000 * 60 * 10;
			long begingTime = System.currentTimeMillis();
			while (completeTask < monitors.size()) {
				BaseResult<JSONObject> result = completionService.take().get();
				if (result.isSuccess()) {
					objectList.add((JSONObject) result.getData());
				}
				completeTask++;
				if (System.currentTimeMillis() - begingTime > timeout) {
					break;
				}
			}
			executor.shutdown();
			return objectList;
		}

}
